#include "xml.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h" 

typedef int bool;
#define false 0
#define true !false

/* 在x的第level层（从1开始）插入新的元素 */
static struct xml *
insert_xml(struct xml *x, int level, const char *key, const char *value)
{
	if (x == NULL || key == NULL || value == NULL)
	{
		return (NULL);
	}

	/* 找到第level层 */
	while (--level > 0 && x->child != NULL)
	{
		x = x->child;
		/* 第level层最后一个有效节点 */
		while (x->next != NULL)
		{
			x = x->next;
		}
	}

	/* 创建新的节点 */
	struct xml *new_node = NULL;
	if ((new_node = create_xml()) == NULL)
	{
		return (NULL);
	}
	snprintf(new_node->key, sizeof(new_node->key), "%s", key);
	snprintf(new_node->value, sizeof(new_node->value), "%s", value);
	new_node->type = XML_ELEMENT;

	/* 在第level层的双向链表插入数据 */
	if (level != 0)  /* 第level层不存在 */
	{
		x->type = XML_OBJECT;
		x->child = new_node;
	}
	else
	{
		x->next = new_node;
		new_node->prev = x;
	}

	return (x);
}

/* 获取<key>或者</key>中的value，并赋值给参数key指向的地址
 * 返回指向'>'之后的字符的地址
 * 注意:
 *     1)获取key时，必须从第一个有效字符开始，即指向xml_data指向'k'的地址
 *     2)必须保证key的内存地址足够，否则会造成未定义的错误
 */
static char  *
get_tag(char *xml_data, char *key)
{
	if (xml_data == NULL)
	{
		return (NULL);
	}

	bool status = true;
	while (status && *xml_data != '\0')
	{
		switch (*xml_data)
		{
		case ' ':
		case '\n':
		case '\t':
		case '\r':
			return (NULL);  /* key中不应该包好空格，回车等字符，否则出错 */
		case '>':
			xml_data++;
			status = false;  /* 结束 */
			break;
		default:
			*key++ = *xml_data++;
		}

		if (!status)
		{
			break;
		}
	}
	*key = '\0';
	return (xml_data);
}

/* 获取<key>value</key>中的value */
static char *
get_value(char *xml_data, char *value)
{
	if (xml_data == NULL)
	{
		return (NULL);
	}

	bool status = true;
	while (status && *xml_data != '\0')
	{
		switch (*xml_data)
		{
		case ' ':
		case '\n':
		case '\t':
		case '\r':
			xml_data++;   /* 跳过空格，回车等字符 */
			break;
		case '<':
			status = false;   /* 结束 */
			break;
		default:
			*value++ = *xml_data++;
		}

		if (!status)
		{
			break;
		}
	}
	return (xml_data);
}

static char *
skip_comments(char *xml_data)
{
    if (xml_data == NULL)
    {
        return (NULL);
    }
    if (strncmp(xml_data, "!--", strlen("!--")) != 0)
    {
        return (NULL);
    }
    /* comment */
    char *end_comment = NULL;
    if ((end_comment = strstr(xml_data, "-->")) == NULL)
    {
        return (NULL);
    }
    xml_data = end_comment + strlen("-->");

    return (xml_data);
}


/* 创建xml */
struct xml *
create_xml(void)
{
	struct xml *x = NULL;
	if ((x = (struct xml *)malloc(sizeof(struct xml))) != NULL)
	{
		x->prev = NULL;
		x->child = NULL;
		x->next = NULL;
	}
	return (x);
}

/* 销毁xml */
void
destroy_xml(struct xml *x)
{
	if (x != NULL)
	{
		struct xml* free_node = NULL;
		free_node = x;
		x = free_node->next;

		destroy_xml(free_node->child);
		free(free_node);
		destroy_xml(x);
	}
}

/* 由xml数据生成struct xmlli
 * 注意:
 *     1)必须使用destroy_xml释放生成的xml
 */
struct xml *
load_xml(char *xml_data)
{
	if (xml_data == NULL)
	{
		return (NULL);
	}

	bool resolve_status = true;
	/* 创建堆栈 */
	struct stack *s = NULL;
	if ((s = create_stack()) == NULL)
	{
		return (NULL);
	}

	struct xml *x = NULL;
	char key[256];
	char value[256];
	memset(key, 0, sizeof(key));
	memset(value, 0, sizeof(value));
	while (resolve_status && *xml_data != '\0')
	{
		switch (*xml_data)
		{
		case ' ':
		case '\r':
		case '\t':
		case '\n':
			xml_data++;  /* 跳过空格，回车等字符 */
			break;

		case '<':
			xml_data++;
			switch (*xml_data)
			{
			case '\0':
			case ' ':
			case '\r':
			case '\n':
			case '\t':
				resolve_status = false;
				break;
			case '!':  
                if ((xml_data = skip_comments(xml_data)) == NULL)
                {
					resolve_status = false;
                }
				break;   /* break case '!' */

			case '/':   /* end */
				if ((xml_data = get_tag(xml_data + 1, key)) == NULL)
				{
					resolve_status = false;
					break;
				}
				if (top(s) == NULL || strcmp((char *)top(s), key) != 0)
				{
					resolve_status = false;
					break;  
				}

				pop(s);
				break;
			default:  /* begin */
				memset(key, 0, sizeof(key));
				if ((xml_data = get_tag(xml_data, key)) == NULL)
				{
					resolve_status = false;
					break;
				}
				push(s, key, strlen(key));

				memset(value, 0, sizeof(value));
				xml_data = get_value(xml_data, value);
				/* 获取栈中的元素个数，表示当前创建的是第几层节点 */
				int level = get_element_num(s);
				if (x == NULL)  /* root */
				{
					if ((x = create_xml()) == NULL)
					{
						destroy_stack(s);
						return (NULL);
					}
					x->type = XML_ELEMENT;
					snprintf(x->key, sizeof(x->key), "%s", key);
					snprintf(x->value, sizeof(x->value), "%s", value);
				}
				else
				{
					if (insert_xml(x, level, key, value) == NULL)
					{
						destroy_stack(s);
						destroy_xml(x);
						return (NULL);
					}
				}

			}
			break;  /* break case '<' */

		default:
			goto errout;
		}
	}

	if (is_empty(s) != 1)
	{
		resolve_status = false;
	}

errout:
	if (!resolve_status)
	{
		destroy_xml(x);
		x = NULL;
	}
	destroy_stack(s);
	return (x);
}

/* 输出xml到xml_data中 */
int
print_xml(const struct xml* x, char* xml_data, int size)
{
	if (x == NULL || xml_data == NULL)
	{
		return (0);
	}

	int total_print = 0;
	while (x != NULL)
	{
		total_print += snprintf(xml_data + total_print, size - total_print, "<%s>", x->key);

		if (strlen(x->value) != 0)
		{
			total_print += snprintf(xml_data + total_print, size - total_print, "%s", x->value);
		}

		total_print += print_xml(x->child, xml_data + total_print, size - total_print);

		total_print += snprintf(xml_data + total_print, size - total_print, "</%s>", x->key);

		x = x->next;
	}

	return (total_print);
}

/* 获取xml第一个key值，用于获取key-value */
struct xml *
get_first_xml_object(struct xml *x, const char *key)
{
	while (x != NULL)
	{
		if (x->key != NULL && strcmp(x->key, key) == 0)
		{
			return (x);
		}
		struct xml *tmp = NULL;
		if ((tmp = get_first_xml_object(x->child, key)) != NULL)
		{
			return (tmp);
		}
		x = x->next;
	}
	return (NULL);
}

/* 通过模型(M)的名称获取对应的xml */
struct xml *
get_mode_xml(struct xml *x, const char *mode_name)
{
	while (x != NULL)
	{
		if (x->key != NULL && strcmp(x->key, "class") == 0)
		{
			struct xml* class_name = NULL;
			if ((class_name = get_first_xml_object(x, "class-name")) != NULL 
				&& class_name->value != NULL && strcmp(class_name->value, mode_name) == 0)
			{
				return (x);
			}
		}

		struct xml *tmp = NULL;
		if ((tmp = get_mode_xml(x->child, mode_name)) != NULL)
		{
			return (tmp);
		}
		x = x->next;
	}
	return (NULL);
}

/* 在x中获取相对与b的下一个key,用于获取模型(M)中的下一个class-member */
struct xml *
get_xml_by_brothers(struct xml *x, struct xml *b, const char *key)
{
	if (b == NULL)
	{
		return (get_first_xml_object(x, key));
	}

	while (x != NULL)
	{
		if (x == b && x->next != NULL && x->next->key != NULL && strcmp(x->next->key, key) == 0)
		{
			return (x->next);
		}
		struct xml *tmp = NULL;
		if ((tmp = get_xml_by_brothers(x->child, b, key)) != NULL)
		{
			return (tmp);
		}
		x = x->next;
	}
	return (NULL);
}

/* 创建xml根节点并赋值 */
struct xml *
create_xml_and_assigment(const char *key, const char *value)
{
	if (key == NULL)
	{
		return (NULL);
	}

    struct xml *root = NULL;
    if ((root = create_xml()) == NULL)
    {
        return (NULL);
    }

	root->type = XML_ELEMENT;
	memset(root->key, 0, sizeof(root->key));
	memset(root->value, 0, sizeof(root->value));
	memcpy(root->key, key, sizeof(root->key));
	if (value != NULL)
	{
		memcpy(root->value, value, sizeof(root->value));
	}
	return (root);
}

/* 将child插入到x的子节点中 */
struct xml *
insert_xml_child(struct xml *x, struct xml *child)
{
	if (x == NULL)
	{
		return (NULL);
	}

	if (x->child == NULL)
	{
		x->type = XML_OBJECT;
		x->child = child;
	}
	else
	{
		x = x->child;
		while (x->next != NULL)
		{
			x = x->next;
		}
		x->next = child;
	}
	return (child);
}

/* 将x同一级插入node */
struct xml *
insert_xml_brother(struct xml *x, struct xml *node)
{
	if (x == NULL || node == NULL)
	{
		return (NULL);
	}
	while (x->next != NULL)
	{
		x = x->next;
	}
	x->next = node;
	return (node);
}
